package com.java1234.controller;

import com.github.pagehelper.PageInfo;
import com.java1234.common.constant.MqConstants;
import com.java1234.entity.Operationlogs;
import com.java1234.entity.R;
import com.java1234.entity.Article;
import com.java1234.service.OperationLogsService;
import com.java1234.service.impl.ArticleServiceImpl;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

/**
 * 文章Controller
 */
@RestController
@Slf4j
@RequestMapping("/bsns/gradInfor/messages")
public class ArticleController {
    private static final Logger logger = LoggerFactory.getLogger(ArticleController.class);
    @Autowired
    private OperationLogsService operationlogsService; // 注入操作日志服务

    @Resource
    private ArticleServiceImpl articleService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostMapping("/deleteById/{id}")
    public R deleteById(@PathVariable("id") Integer id, HttpServletRequest request) {
        logger.info("删除文章信息: {}", id);
        try {
            articleService.deleteById(id);
            rabbitTemplate.convertAndSend(MqConstants.ARTICLE_EXCHANGE, MqConstants.ARTICLE_DELETE_KEY, id);
            // 同步删除 Elasticsearch 中的文档
            deleteFromElasticsearch(id);
            // 记录操作日志
            logOperation(request, "删除文章", "POST /bsns/gradInfor/messages/deleteById/{id}", "文章ID: " + id, "成功");
            return R.ok();


        } catch (Exception e) {
            logOperation(request, "删除文章", "POST /bsns/gradInfor/messages/deleteById/{id}", "文章ID: " + id, "失败");
            return R.error("删除文章失败: " + e.getMessage());
        }
    }

    @PostMapping("/deleteBatch")
    public R deleteBatch(@RequestBody List<Integer> ids, HttpServletRequest request) {
        logger.info("批量删除文章信息: {}", ids);
        try {
            articleService.deleteBatch(ids);
            rabbitTemplate.convertAndSend(MqConstants.ARTICLE_EXCHANGE, MqConstants.ARTICLE_DELETE_KEY, ids);
            for (Integer id : ids){
                deleteFromElasticsearch(id);
            }
            // 记录操作日志
            logOperation(request, "批量删除文章", "POST /bsns/gradInfor/messages/deleteBatch", "文章ID列表: " + ids, "成功");
            return R.ok();
        } catch (Exception e) {
            logOperation(request, "批量删除文章失败", "POST /bsns/gradInfor/messages/deleteBatch", "文章ID列表: " + ids, "失败: " + e.getMessage());
            return R.error("批量删除文章失败: " + e.getMessage());
        }
    }

    @PostMapping("/update")
    public R update(@RequestBody Article article,HttpServletRequest request) {
        logger.info("更新文章信息: {}", article);
        try {

            Article savedArticle = articleService.update(article);

            // 获取自增的 ID
            Integer id = savedArticle.getId();
            rabbitTemplate.convertAndSend(MqConstants.ARTICLE_EXCHANGE, MqConstants.ARTICLE_INSERT_KEY, article.getId());
            // 同步更新 Elasticsearch 中的文档
            updateToElasticsearch(article);
            logOperation(request, "更新文章", "POST /bsns/gradInfor/messages/update", "文章信息: " + article, "成功");
            return R.ok().put("id", id);
        } catch (Exception e) {
            logOperation(request, "更新文章", "POST /bsns/gradInfor/messages/update", "文章信息: " + article, "失败: " + e.getMessage());
            return R.error("更新文章失败: " + e.getMessage());
        }
    }
    /*
     * 新增文章
     * @param article
     */
    @PostMapping("/add")
    public R add(@RequestBody Article article,HttpServletRequest request) {
        logger.info("新增文章信息: {}", article);
        try {
            // 保存文章到数据库
            Article savedArticle = articleService.add(article);

            // 获取自增的 ID
            Integer id = savedArticle.getId();

            rabbitTemplate.convertAndSend(MqConstants.ARTICLE_EXCHANGE, MqConstants.ARTICLE_INSERT_KEY, id);
            // 同步新增到 Elasticsearch
            saveToElasticsearch(savedArticle);
            logOperation(request, "新增文章", "POST /bsns/gradInfor/messages/add", "文章信息: " + article, "成功");
            return R.ok().put("id", id);
        } catch (Exception e) {
            logOperation(request, "新增文章", "POST /bsns/gradInfor/messages/add", "文章信息: " + article, "失败: " + e.getMessage());
            return R.error("消息发送失败: " + e.getMessage());
        }
    }
    /*
     * 查询所有文章
     * @param article
     */
    @GetMapping("/selectAll")
    public R selectAll(Article article,HttpServletRequest request){
        logger.info("查询所有文章信息: {}", article);
        List<Article> list = articleService.selectAll(article);
       logOperation(request, "查询所有文章", "GET /bsns/gradInfor/messages/selectAll", "查询条件: " + article, "成功");
        return R.ok(list);
    }
    /*
     * 根据id查询文章
     * @param id
     */
    @GetMapping("/selectById/{id}" )
    public R selectById(@PathVariable("id") Integer id,HttpServletRequest request){
        logger.info("查询文章信息: {}", id);
        Article article=articleService.selectById(id);
        logOperation(request, "查询文章", "GET /bsns/gradInfor/messages/selectById/{id}", "文章ID: " + id, "成功");
        return R.ok(article);
    }

    /*
     * 分页查询
     * @param article
     * @param pageNum
     * @param pageSize
     */
    //分页查询
    //pageNum当前页,pageSize每个页的个数
    @GetMapping("/selectPage")
    public R selectPage(Article article,
                    @RequestParam(defaultValue = "1") Integer pageNum,
                             @RequestParam(defaultValue = "10") Integer pageSize,HttpServletRequest request){
        logger.info("分页查询文章信息: {}, pageNum: {}, pageSize: {}", article, pageNum, pageSize);
        PageInfo<Article> pageInfo=articleService.selectPage(article,pageNum,pageSize);
        logOperation(request, "分页查询文章", "GET /bsns/gradInfor/messages/selectPage", "查询条件: " + article + ", pageNum: " + pageNum + ", pageSize: " + pageSize, "成功");
        return R.ok(pageInfo);
    }

    /**
     * 同步删除到 Elasticsearch
     * @param id
     */
    private void deleteFromElasticsearch(Integer id) {
        try {
            // 假设你已经配置好了 Elasticsearch 客户端
            RestHighLevelClient client =  new RestHighLevelClient(RestClient.builder(
                    HttpHost.create("http://localhost:9200")
            ));

            // 构建删除请求
            DeleteRequest deleteRequest = new DeleteRequest("article", id.toString());

            // 执行删除操作
            DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);

            // 检查删除操作的状态
            if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {
                log.warn("Elasticsearch 中未找到 ID 为 {} 的文档", id);
            } else {
                log.info("成功删除 Elasticsearch 中的文档，ID: {}", id);
            }
        } catch (IOException e) {
            log.error("删除 Elasticsearch 文档失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 将文章保存到 Elasticsearch
     *
     * @param article 文章对象
     */
    private void saveToElasticsearch(Article article) {
        try {
            // 假设你已经配置好了 Elasticsearch 客户端
            RestHighLevelClient client =  new RestHighLevelClient(RestClient.builder(
                    HttpHost.create("http://localhost:9200")
            ));

            // 构建索引请求
            IndexRequest indexRequest = new IndexRequest("article") // 索引名称
                    .id(article.getId().toString()) // 文档 ID
                    .source(convertArticleToMap(article), XContentType.JSON); // 文档内容

            // 执行索引操作
            IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);

            // 检查索引操作的状态
            if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
                log.info("成功新增到 Elasticsearch，ID: {}", article.getId());
            } else {
                log.warn("Elasticsearch 文档已存在，执行了更新操作，ID: {}", article.getId());
            }
        } catch (IOException e) {
            log.error("新增到 Elasticsearch 失败: {}", e.getMessage(), e);
        }
    }
    private void updateToElasticsearch(Article article) {
        try {
            // 假设你已经配置好了 Elasticsearch 客户端
            RestHighLevelClient client =  new RestHighLevelClient(RestClient.builder(
                    HttpHost.create("http://localhost:9200")
            ));

            // 构建更新请求
            UpdateRequest updateRequest = new UpdateRequest("article", article.getId().toString()) // 索引名称和文档 ID
                    .doc(convertArticleToMap(article)) // 更新内容
                    .docAsUpsert(true); // 如果文档不存在，则插入

            // 执行更新操作
            UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);

            // 检查更新操作的状态
            if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
                log.info("成功更新 Elasticsearch 中的文档，ID: {}", article.getId());
            } else if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) {
                log.info("Elasticsearch 中不存在该文档，已插入新文档，ID: {}", article.getId());
            }
        } catch (IOException e) {
            log.error("更新 Elasticsearch 文档失败: {}", e.getMessage(), e);
        }
    }


    /**
     * 将 Article 对象转换为 Map
     *
     * @param article 文章对象
     * @return Map 对象
     */
    private Map<String, Object> convertArticleToMap(Article article) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", article.getId());
        map.put("title", article.getTitle());
        map.put("time", article.getTime());
        map.put("articleType", article.getArticleType());
        // 添加其他字段...
        return map;
    }


    private void logOperation(HttpServletRequest request, String operation, String method, String params, String result) {
        Operationlogs log = new Operationlogs();
        log.setUsername(getCurrentUsername());
        log.setOperation(operation);
        log.setMethod(method);
        log.setParams(params);
        log.setResult(result);
        log.setElapsedTime(0L); // 可以计算实际耗时
        log.setCreateTime(new Date());
        log.setIpAddress(request.getRemoteAddr());
        log.setStatus("OK");
        operationlogsService.logOperation(log);
    }
    private String getCurrentUsername() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
            return ((UserDetails) principal).getUsername();
        } else {
            return principal.toString();
        }
    }

}
